package com.heima.search.service.impl;

import com.heima.common.excpetion.CustException;
import com.heima.es.service.EsService;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.search.dtos.UserSearchDTO;
import com.heima.model.search.vos.SearchArticleVO;
import com.heima.model.threadlocal.AppThreadLocalUtils;
import com.heima.model.user.pojos.ApUser;
import com.heima.search.service.ApUserSearchService;
import com.heima.search.service.ArticleSearchService;
import org.apache.commons.collections.CollectionUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * app端文章搜索实现类
 */
@Service("ArticleSearchService")
public class ArticleSearchServiceImpl implements ArticleSearchService {
    public static final String APP_INFO_ARTICLE = "app_info_article";

    @Value("${file.minio.readPath}")
    String readPath;

    @Value("${file.oss.web-site}")
    String webSite;

    @Autowired
    EsService esService;

    @Autowired
    ApUserSearchService apUserSearchService;

    @Override
    public ResponseResult search(UserSearchDTO userSearchDto) {
        if (userSearchDto == null)
            CustException.cust(AppHttpCodeEnum.PARAM_REQUIRE);

        //获取输入的关键字
        String searchWords = userSearchDto.getSearchWords();
        // 构建查询条件执行查询
        SearchSourceBuilder builder = new SearchSourceBuilder();

        // 异步调用保存用户输入关键词记录
        {
            ApUser user = AppThreadLocalUtils.getUser();
            if (user != null)
                userSearchDto.setEntryId(user.getId());

            apUserSearchService.insert(userSearchDto);
        }

        // 构建查询条件和过滤
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        // 添加条件
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("title", searchWords);
        //装入条件
        boolQueryBuilder.must(matchQuery);

        // 添加条件: 查询小于minDate的数据
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime").lt(userSearchDto.getMinBehotTime().getTime());
        boolQueryBuilder.filter(rangeQueryBuilder);

        // 添加条件: 分页
        builder.from(userSearchDto.getFromIndex());
        builder.size(userSearchDto.getPageSize());

        // 添加条件: 按照发布时间倒序
        builder.sort("publishTime", SortOrder.DESC);

        // 设置关键字高亮 三要素
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title"); // 高亮的字段
        highlightBuilder.preTags("<font style='color: red; font-size: inherit;'>"); //高亮词的前缀
        highlightBuilder.postTags("</font>"); //高亮词的后缀

        //放入查询参数查询
        builder.highlighter(highlightBuilder);
        builder.query(boolQueryBuilder);
        PageResponseResult result = esService.search(builder, SearchArticleVO.class, APP_INFO_ARTICLE);

        //返回结果 staticUrl 拼接 minIO文章服务器的前缀路径

        List<SearchArticleVO> list = (List<SearchArticleVO>) result.getData();
        list = list.stream().map(searchArticleVO -> {
            searchArticleVO.setStaticUrl(readPath + searchArticleVO.getStaticUrl());
            searchArticleVO.setImages(webSite + searchArticleVO.getImages());
            return searchArticleVO;
        }).collect(Collectors.toList());
        result.setData(list);
        return result;
    }

    /**
     * Es索引库自动更新文章
     *
     * @param article 文章ID
     */
    @Override
    public void saveArticle(SearchArticleVO article) {
        esService.save(article, APP_INFO_ARTICLE);
    }

    /**
     * Es索引库自动删除文章
     *
     * @param articleId 文章ID
     */
    @Override
    public void deleteArticle(String articleId) {
        esService.deleteById(APP_INFO_ARTICLE, articleId);
    }
}
